\section{\PTBRph{}}

Quando o autor desse livro começou a aprender C e depois C++, ele costumava escrever pequenos pedaços de código, compilar e entã o olhar na sua saída em assembly.
Isso acabou tornando muito fácil para o seu entendimento sobre o que estava acontecendo no código que ele escreveu.
Ele fez isso tantas vezes, que a relação entre o código em \CCpp e o que o compilador produzia ficou gravada em sua mente.
É facil imaginar a aparência e função de um rascunho em C. Algumas vezes essa técnica pode ser útil para outras pessoas.

Ás vezes compiladores antigos serão usados aqui com o objetivo de conseguir o menor (ou mais simples) pedaço de código possível.

\iffalse
% other version...
Quando o autor deste livro começou a aprender C e, mais tarde, \Cpp, ele costumava escrever pequenos pedaços de código, compilá-los, 
e então olhar a saída em linguagem assembly. Isso tornou muito fácil para ele entender o que estava acontecendo no código que ele tinha escrito.
\footnote{Na verdade, ele ainda faz isso quando não consegue entender o que faz um determinado pedaço de código.}. 
Ele fez isso tantas vezes que o relacionamento entre o código \CCpp code e o que o compilador produzia ficou registrado profundamente em sua mente. 
É fácil imaginar de imediato um esboço da aparência e função do código C. 
Talvez essa técnica poderia ser útil para mais alguém.

%Há uma série de exemplos para ambos x86/x64 e ARM.
%Aqueles já familiarizados com alguma das arquiteturas, pode ler superficialmente as próximas páginas.

Em determinadas partes foram usados aqui compiladores muito antigos, para se obter o menor (ou mais simples) snippet possível.
\fi
\ac{TBT}.
\section*{\Exercises}

Quando o autor deste livro estudou a linguagem assembly, ele também frequentemente compilava pequenas funções em C e então as reescrevia gradualmente em assembly, tentando fazer seu código o menor possível.
Provavelmente não vale mais à pena fazer isso em cenários reais atualmente, 
porque é difícil competir com os compiladores modernos em termos de eficiência. É, no entanto, uma forma muito boa de obter um melhor entendimento de assembly.
Sinta-se livre, portanto, para pegar qualquer código assembly deste livro e tentar torná-lo menor.
No entanto, não esqueça de testar o que você tiver escrito.

\section*{Níveis de otimização e informações de depuração}

O código-fonte pode ser compilado por um número diferente de compiladores com vários níveis de otimização.
Um compilador típico tem por volta de três desses níveis, onde o nível zero representa que a otimização está desabilitada.
A otimização também pode ser relacionada com o tamanho ou velocidade do código.
Um compilador não-otimizado é mais rápido e produz um código de mais fácil compreensão (embora detalhado),
enquanto um compilador com otimização é mais lento e tenta produzir códigos que executam mais rápido (mas não necessariamente mais compactos).
Em adição aos níveis de otimização e  direção, um compilador pode incluir no arquivo de saída algumas informações de depuração, dessa maneira produzindo código para fácil depuração.
Uma das características de um código ``depurado'' é que ele pode conter ligações entre cada linha do código-fonte e o endereço do respectivo código de máquina.
Compiladores otimizadores, por outro lado, tendem a produzir saídas onde linhas completas do código-fonte podem ser otimizadas e apresentadas de uma maneira completamente diferente,
muitas vezes ainda nem estando presente no código de máquina resultate. Com a engenharia reversa podemos obter quaisquer versões,
simplesmente porque alguns desenvolvedores ativam as otimizações do compilador e outros não.
Por causa disso, nós tentaremos trabalhar em ambos exemplos de depuração e versões de lançamento dos códigos demonstrados nesse livro, quando possível.

\iffalse
% another version
\section*{Níveis de otimização e informação de depuração}

O código-fonte pode ser compilado por diferentes compiladores com vários níveis de otimização.
Um compilador típico tem cerca de três destes níveis, onde o nível zero significa desativar a otimização.
A otimização também pode ser direcionada para o tamanho do código ou para a velocidade do código.
Um compilador sem otimização é mais rápido e produz código mais inteligível (embora maior),
enquanto que um compilador com otimização é mais lento e tenta produzir um código que execute mais rápido (mas não é necessariamente mais compacto).
Além dos níveis e direcionamento da otimização, o compilador pode incluir no arquivo resultante algumas informações de depuração, produzindo assim código para fácil depuração.
Uma das características importantes do código de ´debug' é que ele pode conter 
ligações entre cada linha do código-fonte e os respectivos endereços de código de máquina.
Compiladores com otimização, por outro lado, tendem a produzir uma saída onde linhas inteiras de código-fonte podem ser otimizadas a ponto de serem removidas e portanto não estarem presentes no código de máquina resultante.
Engenheiros Reversos podem encontrar ambas as versões, simplesmente porque alguns desenvolvedores ativam as flags de otimização do compilador e outros não ativam. 
Por causa disso, nós tentaremos trabalhar em exemplos de ambas as versões de debug e release do código destacado neste livro, onde possível.
\fi
